package cn.tannn.ops.util;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;

import static cn.tannn.ops.util.FileUtil.pathAppend;

/**
 * 数据库工具
 *
 * @author <a href="https://t.tannn.cn/">tan</a>
 * @version V1.0
 * @date 2024/9/10 上午10:01
 */
@Slf4j
public class DbUtil {

    /**
     * 通过 mysqlDump 备份数据库数据
     *
     * @param session          {@link SSHUtil#connectionServer(String, String, String, int)}
     * @param user             数据库用户名
     * @param pass             数据库密码
     * @param host             数据库地址
     * @param port             数据库端口
     * @param dbName           数据库名
     * @param mysqlDumpPath    mysqldump在SSH服务器上的路 [通过 which mysqldump 查询] (docker的话格式为docker exec mysql /usr/bin/mysqldump)
     * @param remoteBackupPath 备份文件保存路径
     * @return 备份文件绝对路径(物理机)
     * @throws JSchException jsch异常
     * @throws IOException   io异常
     */
    public static String mysqlDumpBackup(Session session
            , String user
            , String pass
            , String host
            , int port
            , String dbName
            , String mysqlDumpPath
            , String remoteBackupPath) throws JSchException, IOException {
        Channel channel = null;
        String remoteFile;
        try {

            String backupFileName = dbName + "_" + System.currentTimeMillis() + ".sql";
            // 绝对路径需要预先创建好文件
            // 远程文件绝对路径
            remoteFile = pathAppend(remoteBackupPath) + backupFileName;
            // 创建文件，一直都是物理机上创建，如果是docker的话会自己映射
            SSHUtil.createFile(session, remoteBackupPath, backupFileName);

            String command = String.format("%s -h127.0.0.1 -P%d -u%s -p%s %s > %s",
                    mysqlDumpPath, port, user, pass, dbName, remoteFile);
            log.debug("mysqlDumpBackup command: {}", command);
            // 开启 channel
            channel = session.openChannel("exec");
            // 执行  mysqldump 命令
            ((ChannelExec) channel).setCommand(command);
            // 获取命令执行后的数据流
            InputStream in = channel.getInputStream();
            // 连接 channel
            channel.connect();
            // 读取命令执行后的数据流
            while (true) {
                // 循环判断是否执行完成
                if (channel.isClosed()) {
                    if (in.available() > 0) {
                        continue;
                    }
                    log.info("mysqlDumpBackup exit-status: {}", channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {
                }
            }
            // 关闭 channel
            channel.disconnect();
        } catch (JSchException e) {
            log.error("shh exceptions", e);
            throw e;
        } catch (IOException e) {
            log.error("exec run", e);
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (channel != null && channel.isConnected()) {
                channel.disconnect();
            }
        }
        return remoteFile;
    }
}
